package com.engine4cloud.tdf.education.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.engine4cloud.tdf.common.core.constant.enums.YesNoEnum;
import com.engine4cloud.tdf.common.core.exception.ValidateCodeException;
import com.engine4cloud.tdf.common.core.util.lambda.Actions;
import com.engine4cloud.tdf.common.data.web.query.Pages;
import com.engine4cloud.tdf.common.data.web.query.Queries;
import com.engine4cloud.tdf.common.data.web.response.PageInfo;
import com.engine4cloud.tdf.common.data.web.response.Params;
import com.engine4cloud.tdf.common.security.service.TdfUser;
import com.engine4cloud.tdf.common.security.util.SecurityUtils;
import com.engine4cloud.tdf.education.convert.EduCourseConvert;
import com.engine4cloud.tdf.education.dto.EduCourseResourcePushDTO;
import com.engine4cloud.tdf.education.dto.create.EduCourseCreateDTO;
import com.engine4cloud.tdf.education.dto.query.EduCourseQueryDTO;
import com.engine4cloud.tdf.education.dto.result.EduCourseResultDTO;
import com.engine4cloud.tdf.education.dto.update.EduCourseUpdateDTO;
import com.engine4cloud.tdf.education.entity.EduCourseEntity;
import com.engine4cloud.tdf.education.entity.EduCourseGroupEntity;
import com.engine4cloud.tdf.education.entity.EduCourseResourceEntity;
import com.engine4cloud.tdf.education.mapper.EduCourseMapper;
import com.engine4cloud.tdf.education.service.*;
import jakarta.annotation.Resource;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 课程
 *
 * @author wenjie
 * @date 2024-07-30 14:56:55
 */
@Service
public class EduCourseServiceImpl extends ServiceImpl<EduCourseMapper, EduCourseEntity> implements EduCourseService {
    @Resource
    private EduCourseResourceService courseResourceService;

    @Resource
    private EduResourceService resourceService;

    @Resource
    private EduCourseGroupService courseGroupService;

    @Resource
    private EduGroupService groupService;

    @Resource
    private EduStudyTaskService studentResourceService;

    @Override
    public PageInfo<EduCourseResultDTO> pageList(Params pageable, EduCourseQueryDTO dto) {
        return Pages.convert(this.baseMapper.pageList(Pages.page(pageable), dto));
    }

    @Override
    public EduCourseResultDTO getById(Long id) {
        EduCourseResultDTO result = EduCourseConvert.INSTANCE.convert(super.getById(id));
        //设置资源
        result.setResourceList(resourceService.findListByCourse(result.getCode()));
        //设置学组
        result.setGroupList(groupService.findListByCourseCode(result.getCode()));
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String create(EduCourseCreateDTO dto) {
        TdfUser user = SecurityUtils.getUser();
        EduCourseEntity entity = EduCourseConvert.INSTANCE.create(dto, user.getTenantId());
        super.save(entity);
        //保存关联资源
        Actions.apply(CollectionUtils.isNotEmpty(dto.getResourceList()), () -> courseResourceService.batchCreate(entity.getCode(), dto.getResourceList()));
        //保存课程学组关系
        Actions.apply(CollectionUtils.isNotEmpty(dto.getGroupList()), () -> courseGroupService.batchCreate(entity.getCode(), dto.getGroupList()));
        return entity.getCode();
    }

    /**
     * 课程编辑，不允许编辑资源和学组
     *
     * @param dto dto
     * @return Boolean
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean update(EduCourseUpdateDTO dto) {
        EduCourseEntity old = Optional.ofNullable(this.baseMapper.selectById(dto.getId()))
                .orElseThrow(() -> new ValidateCodeException("数据不存在"));

        EduCourseEntity entity = EduCourseConvert.INSTANCE.update(dto);
        super.updateById(entity);
        //保存关联资源
        Actions.apply(CollectionUtils.isNotEmpty(dto.getResourceList()), () -> courseResourceService.batchUpdate(old.getCode(), dto.getResourceList()));
        //保存课程学组关系
        Actions.apply(CollectionUtils.isNotEmpty(dto.getGroupList()), () -> courseGroupService.batchUpdate(old.getCode(), dto.getGroupList()));
        return true;
    }

    /**
     * 推送课程，实际上是将学员和资源建立关系，如果没有推送，则学员看不到资源，
     * 说明：多次调用该接口时，如果一个学生已经有了该课程和学组下的资源，就不再推送
     *
     * @param code 课程编号
     * @return Boolean
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean pushAll(String code) {
        EduCourseEntity old = Optional.ofNullable(this.getOne(wrapper(new EduCourseQueryDTO(code))))
                .orElseThrow(() -> new ValidateCodeException("数据不存在"));

        if (Objects.equals(YesNoEnum.YES.getCode(), old.getIsPublish())) {
            throw new ValidateCodeException("课程已发布，不能再次发布");
        }

        //查询学组
        List<EduCourseGroupEntity> groupList = courseGroupService.findList(old.getCode());
        if (CollectionUtils.isEmpty(groupList)) {
            throw new ValidateCodeException("请设置学组");
        }

        //查询资源
        List<EduCourseResourceEntity> resourceList = courseResourceService.findList(old.getCode());
        if (CollectionUtils.isEmpty(resourceList)) {
            throw new ValidateCodeException("请设置学习资源");
        }

        List<String> groupCodeList = groupList.stream().map(EduCourseGroupEntity::getGroupCode).toList();
        List<String> resourceCodeList = resourceList.stream().map(EduCourseResourceEntity::getResourceCode).toList();

        return studentResourceService.createBatch(code, groupCodeList, resourceCodeList);
    }

    @Override
    public Boolean push(EduCourseResourcePushDTO dto) {
        EduCourseEntity old = Optional.ofNullable(this.getOne(wrapper(new EduCourseQueryDTO(dto.getCourseCode()))))
                .orElseThrow(() -> new ValidateCodeException("数据不存在"));

        //查询资源
        List<EduCourseResourceEntity> resourceList = courseResourceService.findList(old.getCode());
        if (CollectionUtils.isEmpty(resourceList)) {
            throw new ValidateCodeException("请设置学习资源");
        }

        List<String> resourceCodeList = resourceList.stream().map(EduCourseResourceEntity::getResourceCode).toList();
        return studentResourceService.createBatch(dto, resourceCodeList);
    }

    private LambdaQueryWrapper<EduCourseEntity> wrapper(EduCourseQueryDTO query) {
        LambdaQueryWrapper<EduCourseEntity> wrapper = Queries.lambda();
        Queries.accept(query.getId(), v -> wrapper.eq(EduCourseEntity::getId, v));
        Queries.accept(query.getCode(), v -> wrapper.eq(EduCourseEntity::getCode, v));
        Queries.accept(query.getIsRequired(), v -> wrapper.eq(EduCourseEntity::getIsRequired, v));
        Queries.accept(query.getIsPublish(), v -> wrapper.eq(EduCourseEntity::getIsPublish, v));
        Queries.accept(query.getProgressType(), v -> wrapper.eq(EduCourseEntity::getProgressType, v));
        Queries.accept(query.getFormat(), v -> wrapper.eq(EduCourseEntity::getFormat, v));
        Queries.accept(query.getName(), v -> wrapper.like(EduCourseEntity::getName, v));
        wrapper.orderByDesc(EduCourseEntity::getCreateTime);
        return wrapper;
    }
}